package com.dsteiner.gwt.cafeteriasophia.client.controller;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.dsteiner.gwt.cafeteriasophia.client.domain.Product;
import com.dsteiner.gwt.cafeteriasophia.client.domain.Sale;
import com.dsteiner.gwt.cafeteriasophia.client.domain.ShiftChange;
import com.dsteiner.gwt.cafeteriasophia.client.model.ShiftChangeSelectionModel;
import com.dsteiner.gwt.cafeteriasophia.client.model.StatisticModel;
import com.dsteiner.gwt.cafeteriasophia.client.rpc.DataService;
import com.dsteiner.widgets.client.Widgets.IFlowPanel;
import com.dsteiner.widgets.client.Widgets.IHTML;
import com.dsteiner.widgets.client.Widgets.ILazyWidget;
import com.dsteiner.widgets.client.Widgets.IWidget;
import com.dsteiner.widgets.client.Widgets.IWidgetBuilder;
import com.dsteiner.widgets.client.Widgets.WidgetListenerAdapter;
import com.dsteiner.widgets.client.domain.Sort;
import com.dsteiner.widgets.client.rpc.SearchRequest;
import com.dsteiner.widgets.client.rpc.SearchResult;
import com.dsteiner.widgets.client.rpc.SearchRequest.SearchRequestImpl;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class StatisticController {

	private StatisticModel statisticModel;
	private IWidgetBuilder widgetBuilder;
	private IFlowPanel contentPanel;
	private IHTML statisticHtml;

	public void registerContentPanel(IFlowPanel contentPanel) {
		this.contentPanel = contentPanel;
	}

	public void registerStatisticHtml(IHTML statisticHtml) {
		this.statisticHtml = statisticHtml;
	}

	public void registerStatisticModel(StatisticModel statisticModel) {
		this.statisticModel = statisticModel;
		statisticModel.addPropertyChangeListener("shiftChanges", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				updateShiftChanges();
			}
		});
		statisticModel.addPropertyChangeListener("shiftChangeSelections", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				updateStatistics();
			}
		});
	}

	public void registerStatisticWidget(ILazyWidget statisticWidget) {
		statisticWidget.addWidgetListener(new WidgetListenerAdapter() {
			@Override
			public void onAttach(IWidget widget) {
				loadShiftChanges();
			}
		});
	}

	public void registerWidgetWidget(IWidgetBuilder widgetBuilder) {
		this.widgetBuilder = widgetBuilder;
	}

	private void loadShiftChanges() {
		SearchRequestImpl searchRequest = new SearchRequestImpl();
		Sort sort = new Sort("date", false);
		searchRequest.setClassName(ShiftChange.class.getName());
		searchRequest.setLimit(20);
		searchRequest.setOffset(0);
		searchRequest.setSort(sort);
		searchRequest.setType(SearchRequest.TYPE_ALL);
		DataService.Util.getInstance().search(searchRequest, new AsyncCallback<SearchResult<ShiftChange>>(){
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
			}
			public void onSuccess(SearchResult<ShiftChange> result) {
				statisticModel.setShiftChanges(result.getObjects());
			}
		});
	}

	private void updateShiftChanges() {
		List<ShiftChange> shiftChanges = statisticModel.getShiftChanges();
		contentPanel.clear();
		for (ShiftChange shiftChange : shiftChanges) {
			ShiftChangeSelectionModel shiftChangeSelectionModel = new ShiftChangeSelectionModel();
			shiftChangeSelectionModel.setShiftChange(shiftChange);
			IWidget widget = widgetBuilder.createWidget(shiftChangeSelectionModel);
			contentPanel.add(widget);
		}
	}

	private void updateStatistics() {
		List<ShiftChange> shiftChangeSelections = statisticModel.getShiftChangeSelections();
		List<ShiftChange> shiftChanges = statisticModel.getShiftChanges();
		StringBuffer sb = new StringBuffer();
		Map<Product, List<Sale>> productSales = new HashMap<Product, List<Sale>>();
		double salesSum = 0;
		double earningsSum = 0;
		double coffeeCountSum = 0;
		for (ShiftChange shiftChange : shiftChangeSelections) {
			double shiftSalesSum = 0;
			double shiftEarningsSum = 0;
			double moneyChange = 0;
			double coffeeCount = 0;
			for (int i = 0; i < Product.products.length; i++) {
				Product product = Product.products[i];
				if(product.isSaleable()){
					double salesValue = shiftChange.getSalesValue(product);
					double earningsValue = shiftChange.getEarnings(product);
					List<Sale> sales = shiftChange.getSales(product);
					List<Sale> salesList = productSales.get(product);
					if(salesList == null){
						salesList = new ArrayList<Sale>();
						productSales.put(product, salesList);
					}
					salesList.addAll(sales);
					shiftSalesSum += salesValue;
					shiftEarningsSum += earningsValue;
				}
				if(product == Product.cafeAmericano || product == Product.cafeLeche ||
						product == Product.cappuccino || product == Product.espresso ||
						product == Product.moccacino || product == Product.chocolate){
					coffeeCount += shiftChange.getSalesSum(product);
				}
			}
			int indexOfCurrentShiftChange = shiftChanges.indexOf(shiftChange);
			if(indexOfCurrentShiftChange < shiftChanges.size() - 1){
				ShiftChange lastShiftChange = shiftChanges.get(indexOfCurrentShiftChange + 1);
				double moneyCalcChange = shiftSalesSum  + shiftChange.getSalesSum(Product.dinero) - shiftChange.getPurchasesSum(Product.dinero);
				double moneyStockChange = shiftChange.getStockSum(Product.dinero) - 
				lastShiftChange.getStockSum(Product.dinero);
				moneyChange = moneyStockChange - moneyCalcChange;
			}
				
//			salesSum += shiftSalesSum + moneyChange;
//			earningsSum += shiftEarningsSum + (moneyChange * 0.35); 
			salesSum += shiftSalesSum;
			earningsSum += shiftEarningsSum;
			coffeeCountSum += coffeeCount;
		}
		double rendite = (earningsSum / salesSum) * 100;
		rendite = Math.round(rendite * 100) / 100.0;
		sb.append("<strong>Ventas:</strong> "+salesSum+"<br>");
		sb.append("<strong>Ganancias:</strong> "+earningsSum+"<br>");
		sb.append("<strong>Rendita:</strong> "+rendite+" %<br><br>");
		sb.append("<strong>Venta Cafe/Chocolate unidad:</strong> "+coffeeCountSum+"<br><br>");
		sb.append("<span style=\"display:inline-block;width:250px;\"><strong>Ventas por producto</strong></span>" +
				"<span style=\"display:inline-block;width:100px;\">Ventas Unidad</span>" +
				"<span style=\"display:inline-block;width:100px;\">Ventas</span>" +
				"<span style=\"display:inline-block;width:100px;\">% del total</span>" +
				"<span style=\"display:inline-block;width:100px;\">Ganancias</span>" +
				"<span style=\"display:inline-block;width:100px;\">% del total</span><br>");
		for (Product product : productSales.keySet()) {
			double salesCount = 0;
			double sales = 0;
			double earnings = 0;
			List<Sale> salesList = productSales.get(product);
			for (Sale sale : salesList) {
				sales += sale.value();
				salesCount += sale.getAmount();
				earnings += sale.value() - (sale.getAmount() * product.getCost());
			}
			if(sales > 0){
				sb.append("<span style=\"display:inline-block;width:250px;\"><strong>").append(product.getName())
				.append("</strong></span><span style=\"display:inline-block;width:100px;\">").append(salesCount)
				.append("</strong></span><span style=\"display:inline-block;width:100px;\">").append(sales)
				.append("</span><span style=\"display:inline-block;width:100px;\">").append(Math.round(sales / salesSum * 100))
				.append("</span><span style=\"display:inline-block;width:100px;\">").append(Math.round(earnings))
				.append("</span><span style=\"display:inline-block;width:100px;\">").append(Math.round(earnings / earningsSum * 100)).append("</span><br>");
			}
		}
		statisticHtml.setHTML(sb.toString());
	}
}